﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using posttrackerApi2.Models;
using posttrackerApi2.Models.TypesHelper;
namespace posttrackerApi2.Controllers
{
    public class UserController : ApiController
    {
        private posttracker_db db = new posttracker_db();


        protected override void Initialize(System.Web.Http.Controllers.HttpControllerContext controllerContext)
        {
           //here could be decryption
            //ControllerContext.Request
            base.Initialize(controllerContext);
        }
        // POST 
        [HttpPost]
        public HttpResponseMessage GetUserByEmail(PutUserRequest request)
        {
           
            UserComming userComming = request.User;
            try
            {
                var user = db.Users.Where(p => p.UserName == userComming.Email && p.IsDeleted != 1).FirstOrDefault();
                if (user == null)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }

                return Request.CreateResponse(HttpStatusCode.OK, getReplayedUser(user));
            }
            catch (WebException)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
            catch (HttpResponseException)
            {
                return Request.CreateResponse(HttpStatusCode.Accepted);
            }

            
        }

        private User GetUserByEmail(string email)
        {
            User user = db.Users.Where(p => p.UserName == email && p.IsDeleted != 1).FirstOrDefault();
            if (user == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }
            return user;
        }

        // POST 
        [HttpPost]
        public HttpResponseMessage PutUser(PutUserRequest request)
        {
            UserComming userComming = request.User;
            int id = request.Id;
            if (ModelState.IsValid && id == userComming.Id)
            {
                User user;
                try
                {
                    user = GetUser(id);
                    user.NameSurname = userComming.UserName;
                    user.UserName = userComming.Email;
                    user.LastActivityDate = DateTime.Now;
                    user.IsLockedOut = userComming.IsLockedOut;
                    //may be unsafe to store password in this way
                    //user.Password = userComming.Password;
                    // also could be unsafe
                    //user.RoleId = userComming.RoleId;
                    //user.Id = userComming.Id;
                
                    db.Entry(user).State = EntityState.Modified;
                }
                catch (HttpResponseException)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }

                try
                {
                    db.SaveChanges();
                }
                catch (DbUpdateConcurrencyException)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }

                return Request.CreateResponse(HttpStatusCode.OK, getReplayedUser(user));
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }
        }
        // POST
        [HttpPost]
        public HttpResponseMessage DeleteUser(PutUserRequest request)
        {
            UserComming userComming = request.User;
            int deleteAllRelatedData = request.Id;
            if (ModelState.IsValid && userComming != null)
            {
                User user;
                try
                {
                    user = db.Users.Where(p => p.NameSurname == userComming.UserName && p.IsDeleted != 1).FirstOrDefault();
                    user.IsDeleted = 1;
                    db.Entry(user).State = EntityState.Modified;
                }
                catch (HttpResponseException)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }

                try
                {
                    db.SaveChanges();
                }
                catch (DbUpdateConcurrencyException)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }

                return Request.CreateResponse(HttpStatusCode.OK, getReplayedUser(user));
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }
        }

        private UserComming getReplayedUser(User user, bool pass = false)
        {
            if (pass)
            return new UserComming() { UserName = "", LastActivityDate = DateTime.Now, IsLockedOut = false, Id = 0, Email = "", Password = user.Password };
            else
                return new UserComming() { UserNameTransfered = user.NameSurname,  UserName = user.NameSurname, LastActivityDate = DateTime.Now, IsLockedOut = false, Id = user.Id, Email = user.UserName };
        }
        // POST
        [HttpPost]
        public HttpResponseMessage AuthenticateUser(PutUserRequest request)
        {
            UserComming userComming = request.User;
            if (ModelState.IsValid && userComming != null)
            {
                User user;
                try
                {
                    user =  db.Users.Where(p => p.NameSurname == userComming.UserNameTransfered && p.IsDeleted != 1).FirstOrDefault();
                    if (user != null && user.NameSurname == userComming.UserNameTransfered && user.Password == userComming.Password)
                    {
                        return Request.CreateResponse(HttpStatusCode.OK, getReplayedUser(user));
                    }
                    else
                    {
                        return Request.CreateResponse(HttpStatusCode.NoContent);
                    }
                }
                catch (HttpResponseException)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }
                             
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }
        }

        // POST 
        public HttpResponseMessage PostUser(UserComming userComming)
        {
            User user = new User() { NameSurname = userComming.UserName, Password = userComming.Password, RoleId = 1, UserName = userComming.Email, LastActivityDate = DateTime.Now, IsLockedOut=false, IsDeleted=0 };
                
                
            if (ModelState.IsValid)
            {
                //create new user
                db.Users.Add(user);
                db.SaveChanges();
                //save Id to reply and erase password due to secure reason
                userComming.Id = user.Id;
                userComming.Password = "";
                //prepare response
                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, userComming);
                response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = user.Id }));
                return response;
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }
          
            //return Request.CreateResponse(HttpStatusCode.OK);
        }
        //POST
        [HttpPost]
        public HttpResponseMessage GetUser(PutUserRequest request)
        {
            UserComming userComming = request.User;
            int updateLastActivityDateFlag = request.Id;
            if (ModelState.IsValid && userComming != null)
            {
                User user;
                if (userComming.Id != 0)
                    user= db.Users.Where(p => p.Id == userComming.Id && p.IsDeleted != 1).FirstOrDefault();
                else if (userComming.UserName != null)
                    user= db.Users.Where(p => p.NameSurname == userComming.UserName && p.IsDeleted != 1).FirstOrDefault();
                else
                    return Request.CreateResponse(HttpStatusCode.BadRequest);

                if (user == null)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }

                if (updateLastActivityDateFlag == 1)
                {

                    user.LastActivityDate = DateTime.Now;
                    db.Entry(user).State = EntityState.Modified;

                    try
                    {
                        db.SaveChanges();
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        return Request.CreateResponse(HttpStatusCode.NotFound);
                    }


                }

                return Request.CreateResponse(HttpStatusCode.OK, getReplayedUser(user));

            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }

            
        }
        //POST
        [HttpPost]
        public HttpResponseMessage GetAllUsers(GetAllUsersRequest request)
        {
            GetAllUsersRequest requestData = request;
            List<UserComming> usersList = new List<UserComming>();
            if (ModelState.IsValid && requestData != null)
            {

                var users = db.Users.AsEnumerable().OrderBy(p => p.Id).Where(p => p.IsDeleted != 1).
                    Skip((requestData.pageIndex - 1) * requestData.pageSize).Take(requestData.pageSize);
                var usersCount = db.Users.Where(p => p.IsDeleted != 1).Count();

                foreach (User user in users)
                {
                    usersList.Add(new UserComming() { UserNameTransfered = user.NameSurname, LastActivityDate = DateTime.Now, IsLockedOut = false, Id = user.Id, Email = user.UserName });
                }

                return Request.CreateResponse(HttpStatusCode.OK, new PutUserRequestCollection() { userCollection = usersList, count = usersCount});

            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }


        }

        //POST
        [HttpPost]
        public HttpResponseMessage GetNumberOfUsersOnline(RequestCollection request)
        {
            DateTime requestDate = request.datetime;
         
            if (ModelState.IsValid && requestDate != null)
            {

                var usersOnline = db.Users.Where(p => p.LastActivityDate > requestDate && p.IsDeleted != 1).Count();

                return Request.CreateResponse(HttpStatusCode.OK, usersOnline);

            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }


        }

        //POST
        [HttpPost]
        public HttpResponseMessage GetPassword(PutUserRequest request)
        {
            UserComming userComming = request.User;

            if (ModelState.IsValid && userComming != null)
            {

                var user = db.Users.Where(p => p.NameSurname == userComming.UserName && p.IsDeleted != 1).FirstOrDefault();

                return Request.CreateResponse(HttpStatusCode.OK, getReplayedUser(user, true));

            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }


        }

        //POST
        [HttpPost]
        public HttpResponseMessage ChangePassword(PutUserRequest request)
        {
            UserComming userComming = request.User;
            User user;
            if (ModelState.IsValid && userComming != null)
            {
                try
                {
                    user = db.Users.Where(p => p.NameSurname == userComming.Email && p.Password == userComming.UserName && p.IsDeleted != 1).FirstOrDefault();

                    if (user == null)
                    {
                        throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
                    }
                    user.Password = userComming.Password;
                    db.Entry(user).State = EntityState.Modified;
                }
                catch (HttpResponseException)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }
                try
                {
                    db.SaveChanges();
                }
                catch (DbUpdateConcurrencyException)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }

                return Request.CreateResponse(HttpStatusCode.OK, getReplayedUser(user, true));

            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }


        }

        //POST
        [HttpPost]
        public HttpResponseMessage FindUsersByName(GetAllUsersRequest request)
        {
            GetAllUsersRequest requestData = request;
            List<UserComming> usersList = new List<UserComming>();
            if (ModelState.IsValid && requestData != null)
            {

                var users = db.Users.AsEnumerable().OrderBy(p => p.Id).Where(p => p.NameSurname == request.searchParam && p.IsDeleted != 1).
                    Skip((requestData.pageIndex - 1)* requestData.pageSize).Take(requestData.pageSize);
                var usersCount = db.Users.Where(p => p.NameSurname == request.searchParam && p.IsDeleted != 1).Count();
                foreach (User user in users)
                {
                    usersList.Add(getReplayedUser(user));
                }

                return Request.CreateResponse(HttpStatusCode.OK, new PutUserRequestCollection() { userCollection = usersList, count = usersCount });

            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }


        }


        //POST
        [HttpPost]
        public HttpResponseMessage FindUsersByEmail(GetAllUsersRequest request)
        {
            GetAllUsersRequest requestData = request;
            List<UserComming> usersList = new List<UserComming>();
            if (ModelState.IsValid && requestData != null)
            {

                var users = db.Users.AsEnumerable().OrderBy(p => p.Id).Where(p => p.UserName == request.searchParam && p.IsDeleted != 1).
                    Skip((requestData.pageIndex - 1) * requestData.pageSize).Take(requestData.pageSize);
                var usersCount = db.Users.Where(p => p.NameSurname == request.searchParam && p.IsDeleted != 1).Count();
                foreach (User user in users)
                {
                    usersList.Add(getReplayedUser(user));
                }

                return Request.CreateResponse(HttpStatusCode.OK, new PutUserRequestCollection() { userCollection = usersList, count = usersCount });

            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }


        }

        //POST
        [HttpPost]
        public HttpResponseMessage UnlockUser(PutUserRequest request)
        {
            UserComming userComming = request.User;

            if (ModelState.IsValid && userComming != null)
            {

                var user = db.Users.Where(p => p.NameSurname == userComming.UserName && p.IsDeleted != 1).FirstOrDefault();
                user.IsLockedOut = false;
                db.Entry(user).State = EntityState.Modified;

                try
                {
                    db.SaveChanges();
                }
                catch (DbUpdateConcurrencyException)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }

                return Request.CreateResponse(HttpStatusCode.OK, getReplayedUser(user));

            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }


        }

        // GET api/User
        // BODY OF THE METHOD COMMENTED DUE TO SECURITY REASON
        public IEnumerable<User> GetUsers()
        {
            //return db.Users.AsEnumerable();
            return null;
        }

        // GET api/User/GetUser/5
        // BODY OF THE METHOD COMMENTED DUE TO SECURITY REASON
        public User GetUser(int id)
        {
            User user = db.Users.Where(p => p.Id == id && p.IsDeleted != 1).FirstOrDefault();
            if (user == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }

            return user;
            
        }
        // DELETE api/Tracker/5
        // BODY OF THE METHOD COMMENTED DUE TO SECURITY REASON
        public HttpResponseMessage DeleteUser(int id)
        {
            User user = db.Users.Find(id);
            //if (user == null)
            //{
            //    return Request.CreateResponse(HttpStatusCode.NotFound);
            //}

            //db.Users.Remove(user);

            //try
            //{
            //    db.SaveChanges();
            //}
            //catch (DbUpdateConcurrencyException)
            //{
            //    return Request.CreateResponse(HttpStatusCode.NotFound);
            //}

            return Request.CreateResponse(HttpStatusCode.OK, user);
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}